package com.mask.token.service;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.stereotype.Service;

import java.time.Instant;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicLong;

/**
 * Token性能优化服务
 * 提供Token缓存、批量操作、性能监控等功能
 *
 * @author mask
 * @since 1.0.0
 */
@Slf4j
@Service
@RequiredArgsConstructor
@ConditionalOnProperty(name = "mask.token.performance.enabled", havingValue = "true", matchIfMissing = false)
public class MaskTokenPerformanceService {

    private final MaskTokenService tokenService;

    // 性能统计
    private final AtomicLong tokenGenerationTime = new AtomicLong(0);
    private final AtomicLong tokenValidationTime = new AtomicLong(0);
    private final AtomicLong tokenRefreshTime = new AtomicLong(0);
    private final AtomicLong totalOperations = new AtomicLong(0);

    // 本地缓存（用于热点Token）
    private final ConcurrentHashMap<String, CachedTokenInfo> tokenCache = new ConcurrentHashMap<>();
    private final ConcurrentHashMap<Long, UserTokenSummary> userTokenCache = new ConcurrentHashMap<>();

    /**
     * 缓存Token信息
     */
    public static class CachedTokenInfo {
        private String token;
        private Long userId;
        private Instant expireTime;
        private Instant cacheTime;
        private boolean valid;

        // Constructors, getters, setters
        public CachedTokenInfo(String token, Long userId, Instant expireTime) {
            this.token = token;
            this.userId = userId;
            this.expireTime = expireTime;
            this.cacheTime = Instant.now();
            this.valid = true;
        }

        public boolean isExpired() {
            return Instant.now().isAfter(expireTime);
        }

        public boolean isCacheExpired() {
            return Instant.now().isAfter(cacheTime.plusSeconds(300)); // 5分钟缓存过期
        }

        // Getters and Setters
        public String getToken() { return token; }
        public void setToken(String token) { this.token = token; }
        public Long getUserId() { return userId; }
        public void setUserId(Long userId) { this.userId = userId; }
        public Instant getExpireTime() { return expireTime; }
        public void setExpireTime(Instant expireTime) { this.expireTime = expireTime; }
        public Instant getCacheTime() { return cacheTime; }
        public void setCacheTime(Instant cacheTime) { this.cacheTime = cacheTime; }
        public boolean isValid() { return valid; }
        public void setValid(boolean valid) { this.valid = valid; }
    }

    /**
     * 用户Token摘要
     */
    public static class UserTokenSummary {
        private Long userId;
        private int tokenCount;
        private Instant lastUpdate;
        private java.util.List<String> deviceIds;

        public UserTokenSummary(Long userId) {
            this.userId = userId;
            this.tokenCount = 0;
            this.lastUpdate = Instant.now();
            this.deviceIds = new java.util.ArrayList<>();
        }

        // Getters and Setters
        public Long getUserId() { return userId; }
        public void setUserId(Long userId) { this.userId = userId; }
        public int getTokenCount() { return tokenCount; }
        public void setTokenCount(int tokenCount) { this.tokenCount = tokenCount; }
        public Instant getLastUpdate() { return lastUpdate; }
        public void setLastUpdate(Instant lastUpdate) { this.lastUpdate = lastUpdate; }
        public java.util.List<String> getDeviceIds() { return deviceIds; }
        public void setDeviceIds(java.util.List<String> deviceIds) { this.deviceIds = deviceIds; }
    }

    /**
     * 快速Token验证（使用缓存）
     */
    public boolean fastValidateToken(String token) {
        long startTime = System.currentTimeMillis();
        
        try {
            // 1. 先检查本地缓存
            CachedTokenInfo cachedInfo = tokenCache.get(token);
            if (cachedInfo != null && !cachedInfo.isExpired() && !cachedInfo.isCacheExpired()) {
                totalOperations.incrementAndGet();
                return cachedInfo.isValid();
            }

            // 2. 缓存未命中，执行实际验证
            boolean isValid = tokenService.validateToken(token);
            
            // 3. 更新缓存
            if (isValid) {
                // 从Token中提取用户信息（这里需要实际实现）
                Long userId = extractUserIdFromToken(token);
                Instant expireTime = extractExpireTimeFromToken(token);
                tokenCache.put(token, new CachedTokenInfo(token, userId, expireTime));
            } else {
                tokenCache.put(token, new CachedTokenInfo(token, null, Instant.now()));
            }

            // 4. 记录性能统计
            long duration = System.currentTimeMillis() - startTime;
            tokenValidationTime.addAndGet(duration);
            totalOperations.incrementAndGet();

            return isValid;
        } catch (Exception e) {
            log.error("快速Token验证失败", e);
            return false;
        }
    }

    /**
     * 批量Token验证
     */
    public java.util.Map<String, Boolean> batchValidateTokens(java.util.List<String> tokens) {
        java.util.Map<String, Boolean> results = new java.util.HashMap<>();
        
        for (String token : tokens) {
            results.put(token, fastValidateToken(token));
        }
        
        return results;
    }

    /**
     * 批量清理过期Token
     */
    public int batchCleanExpiredTokens() {
        int cleanedCount = 0;
        
        // 清理本地缓存中的过期Token
        tokenCache.entrySet().removeIf(entry -> {
            CachedTokenInfo info = entry.getValue();
            return info.isExpired() || info.isCacheExpired();
        });
        
        // 清理用户Token缓存
        userTokenCache.entrySet().removeIf(entry -> {
            UserTokenSummary summary = entry.getValue();
            return Instant.now().isAfter(summary.getLastUpdate().plusSeconds(3600)); // 1小时过期
        });
        
        // 执行实际的Token清理
        try {
            tokenService.cleanExpiredTokens();
            cleanedCount = tokenCache.size();
        } catch (Exception e) {
            log.error("批量清理过期Token失败", e);
        }
        
        return cleanedCount;
    }

    /**
     * 预热Token缓存
     */
    public void warmupTokenCache(java.util.List<String> hotTokens) {
        log.info("开始预热Token缓存，Token数量: {}", hotTokens.size());
        
        for (String token : hotTokens) {
            try {
                fastValidateToken(token);
            } catch (Exception e) {
                log.warn("预热Token失败: {}", token, e);
            }
        }
        
        log.info("Token缓存预热完成，缓存大小: {}", tokenCache.size());
    }

    /**
     * 获取性能统计
     */
    public PerformanceStatistics getPerformanceStatistics() {
        PerformanceStatistics stats = new PerformanceStatistics();
        stats.setTotalOperations(totalOperations.get());
        stats.setAverageTokenGenerationTime(tokenGenerationTime.get() / Math.max(1, totalOperations.get()));
        stats.setAverageTokenValidationTime(tokenValidationTime.get() / Math.max(1, totalOperations.get()));
        stats.setAverageTokenRefreshTime(tokenRefreshTime.get() / Math.max(1, totalOperations.get()));
        stats.setCacheSize(tokenCache.size());
        stats.setUserCacheSize(userTokenCache.size());
        stats.setTimestamp(Instant.now());
        
        return stats;
    }

    /**
     * 清理所有缓存
     */
    public void clearAllCache() {
        tokenCache.clear();
        userTokenCache.clear();
        log.info("所有缓存已清理");
    }

    /**
     * 从Token中提取用户ID（需要实际实现）
     */
    private Long extractUserIdFromToken(String token) {
        try {
            return tokenService.getUserIdFromToken(token);
        } catch (Exception e) {
            log.warn("从Token提取用户ID失败", e);
            return null;
        }
    }

    /**
     * 从Token中提取过期时间（需要实际实现）
     */
    private Instant extractExpireTimeFromToken(String token) {
        try {
            com.mask.token.model.TokenInfo tokenInfo = tokenService.getTokenInfo(token);
            return tokenInfo != null ? tokenInfo.getExpireTime() : Instant.now();
        } catch (Exception e) {
            log.warn("从Token提取过期时间失败", e);
            return Instant.now();
        }
    }

    /**
     * 性能统计信息
     */
    public static class PerformanceStatistics {
        private long totalOperations;
        private long averageTokenGenerationTime;
        private long averageTokenValidationTime;
        private long averageTokenRefreshTime;
        private int cacheSize;
        private int userCacheSize;
        private Instant timestamp;

        // Getters and Setters
        public long getTotalOperations() { return totalOperations; }
        public void setTotalOperations(long totalOperations) { this.totalOperations = totalOperations; }
        public long getAverageTokenGenerationTime() { return averageTokenGenerationTime; }
        public void setAverageTokenGenerationTime(long averageTokenGenerationTime) { this.averageTokenGenerationTime = averageTokenGenerationTime; }
        public long getAverageTokenValidationTime() { return averageTokenValidationTime; }
        public void setAverageTokenValidationTime(long averageTokenValidationTime) { this.averageTokenValidationTime = averageTokenValidationTime; }
        public long getAverageTokenRefreshTime() { return averageTokenRefreshTime; }
        public void setAverageTokenRefreshTime(long averageTokenRefreshTime) { this.averageTokenRefreshTime = averageTokenRefreshTime; }
        public int getCacheSize() { return cacheSize; }
        public void setCacheSize(int cacheSize) { this.cacheSize = cacheSize; }
        public int getUserCacheSize() { return userCacheSize; }
        public void setUserCacheSize(int userCacheSize) { this.userCacheSize = userCacheSize; }
        public Instant getTimestamp() { return timestamp; }
        public void setTimestamp(Instant timestamp) { this.timestamp = timestamp; }
    }
}
